package base.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 多线程 争取同于一个共享变量的时候，就会产生 冲突
 * 两种解决方法
 *  1。加锁
 *  2。避免共享，每个线程都拥有一个各自的本地化资源，避免了多线程竞争导致锁的消耗
 * Author: shen qi han
 * Date: 2022/3/20 下午10:15
 */
public class ThreadLocalMain {

    /**
     * desc:
     * use to save self-thread local data
     *
     * data struct:
     * Thread.currentThread() as key
     * then the set(T) T is val
     *
     * oom:
     * the key is weak cite, when gc, key will be null
     * but the entry cited by other Entry
     * so need craft to remove
     *
     */
    ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

    /**
     * use to get localMap val
     */
    class A{
        public void get(){
            // get local thread val
            System.out.println(Thread.currentThread().getName() + " A: " + threadLocal.get());
        }
    }

    class B{
        public void get(){
            // get local thread val
            System.out.println(Thread.currentThread().getName() + " B: " + threadLocal.get());
        }
    }

    /**
     * my thread use to random val then let cur thread to get value
     */
    class MyThread implements Runnable {
        @Override
        public void run() {
            Double v = Math.random() * 10;
            threadLocal.set(v.intValue());
            new A().get();
            new B().get();
            // final need remove threadLocal
            threadLocal.remove();
        }
    }

    /**
     * desc:
     * use to save basic or pack variable
     *
     * result:
     * pool-1-thread-2 A: 8
     * pool-1-thread-1 A: 6
     * pool-1-thread-2 B: 8
     * pool-1-thread-1 B: 6
     *
     * view:
     * we can see the result
     * thread-1, use random val A and B both val 6
     * thread-2, use random val A and B both val 6
     * so, we can know the threadLocal is belonged to current thread keep
     */
    public void testSaveBasicVariable(){
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        int num = 2;
        ExecutorService pool = Executors.newFixedThreadPool(num);
        pool.submit(t1);
        pool.submit(t2);
        pool.shutdown();
    }

    public static void main(String[] args) {
        ThreadLocalMain main = new ThreadLocalMain();
        main.testSaveBasicVariable();
    }


}
